AWS IoT Greengrass Coreにシークレットをデプロイしてみた
はじめに
おはようございます、加藤です。AWS IoT Greengrass Core(以降、Greengrass)でシークレットを扱いたい際に、最も単純な方法はハードコートを行う事です。とはいえ、ハードコートは行いたくないですよね... Greengrassは、AWS Secret Mangaer(以降、Secrets Manger)と連携する事が可能です。これを利用すると、ハードコートを回避できます!!
環境
- pipenv, version 2018.11.26
- Python, 3.7.4
- jq, jq-1.6
- aws-cli, aws-cli/1.16.191 Python/3.7.4 Darwin/18.7.0 botocore/1.12.181
やってみた
シークレットの作成
- Secrets Manager コンソールにサインインします。
- [新しいシークレットを保存する] を選択します。
- [シークレットの種類を選択] で [その他のシークレット] を選択します。
- Greengrassで利用したいシークレットが他の種類である場合は、それを選択します。 4. [このシークレットに格納するキーと値のペアを指定します] で以下の操作を行います。 1. シークレットキー/値を表の通り入力します。
シークレットキー | 値 |
---|---|
test | abcdefghi |
- 暗号化キーに [DefaultEncryptionKey] を選択してから、 [次へ] を選択します。
- [シークレット名に] 「greengrass-TestSecret」 と入力し、 [次へ] を選択します。
- 今回、ローテーションは不要なので、 [自動ローテーションを無効にする] を選択し、 [次へ] を選択します。
- レビューページで、設定を確認し、 [保存] を選択します。
Greengrass グループにローカルシークレットリソースを追加する
- AWS IoT コンソールにサインインし、 [Greengrass] 、 [グループ] の順に選択します。
- シークレットをデプロイするグループを選択します。
- [リソース] 、 [シークレット] の順に選択します。
- [シークレットリソースの追加] を選択します。
- [選択] 、 [greengrass-TestSecret] の順に選択します。
- ラベルの選択(オプション)ページで、 [次へ] を選択します。
- シークレットリソースに名前を付けるページで、設定を確認し、 [保存] を選択します。
Greengrass用のLambda関数のデプロイパッケージ作成
- Pipenvを利用して環境をセットアップします。
mkdir -p src pipenv --python 3.7.4 pipenv install greengrasssdk
- サンプルアプリケーションを作成します。
import greengrasssdk secrets_client = greengrasssdk.client('secretsmanager') message_client = greengrasssdk.client('iot-data') message = '' def function_handler(event, context): response = secrets_client.get_secret_value(SecretId='greengrass-TestSecret') secret_value = response.get('SecretString') if secret_value is None: message = 'Failed to retrieve secret.' else: message = secret_value message_client.publish(topic='secrets/output', payload=message) print('published: ' + message)
- 依存するパッケージを含めて、ソースコードをZIP化します。
pipenv lock -r | pip install -r /dev/stdin -t src/ cd src zip -r ../secret_test_python.zip * cd ../
Greengrass用のLambda関数のデプロイ
- IAMロールの信頼されたエンティティにLambdaを設定する為の、JSONを作成する。
{ "Statement": { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } }
- パラメータを環境変数に設定する。
LAMBDA_FUNCTION_NAME='SecretTest' LAMBDA_ROLE_NAME='secret-test-python'
- IAMロールを作成する。
LAMBDA_ROLE_ARN=$(aws iam create-role \ --role-name ${LAMBDA_ROLE_NAME} \ --assume-role-policy-document file://deploy/trusted_policy_for_lambda.json \ | jq -r '.Role.Arn') aws iam attach-role-policy \ --role-name ${LAMBDA_ROLE_NAME} \ --policy-arn 'arn:aws:iam::aws:policy/AWSLambdaExecute'
- Lambda関数を作成し、バージョンとエイリアスを作成する。
aws lambda create-function \ --function-name ${LAMBDA_FUNCTION_NAME} \ --role ${LAMBDA_ROLE_ARN} \ --runtime 'python3.7' \ --handler 'secret_test.function_handler' \ --zip-file fileb://secret_test_python.zip LAMBDA_VERSION=$(aws lambda publish-version \ --function-name ${LAMBDA_FUNCTION_NAME} \ --description '1' \ | jq -r '.Version') aws lambda create-alias \ --name 'RELEASE' \ --function-name ${LAMBDA_FUNCTION_NAME} \ --function-version ${LAMBDA_VERSION}
Lambda 関数を Greengrass グループに追加する
- AWS IoT コンソールにサインインし、 [Greengrass] 、 [グループ] の順に選択します。
- シークレットをデプロイするグループを選択します。
- [Lambda] 、 [Lambdaの追加] の順に選択します。
- [既存のLambdaの使用] を選択します。
- 同じボタンが2つありますが、どちらを選択しても大丈夫です。 5. [SecretTest] 、 [次へ] を選択します。 6. [エイリアス: RELEASE] 、 [完了] を選択します。
シークレットリソースを Lambda 関数にアタッチする
- グループページで、[Lambda] 、 [SecretTest] の順に選択します。
- [リソース] 、 [シークレット] 、 [シークレットリソースのアタッチ] の順に選択します。
- [シークレットリソースの選択] を選択します。
- [MyTestSecret] 、 [保存] の順に選択します。
サブスクリプションを Greengrass グループに追加する
- グループページで、[サブスクリプション] 、 [サブスクリプションの追加] の順に選択します。
- [ソースとターゲットの選択] で以下の操作を行います。
- ソースの選択/ターゲットの選択を表の通り入力します。
ソースの選択 | ターゲットの選択 |
---|---|
IoT Cloud | SecretTest |
- [次へ] を選択します。
- [トピックフィルター] に [secrets/input] と入力し、 [次へ] を選択します。
- [完了] を選択します。
続けて、逆方向も追加します。
- グループページで、[サブスクリプション] 、 [サブスクリプションの追加] の順に選択します。
- [ソースとターゲットの選択] で以下の操作を行います。
- ソースの選択/ターゲットの選択を表の通り入力します。
ソースの選択 | ターゲットの選択 |
---|---|
SecretTest | IoT Cloud |
- [次へ] を選択します。
- [トピックフィルター] に [secrets/output] と入力し、 [次へ] を選択します。
- [完了] を選択します。
Greengrass のデプロイ
- グループページで、[アクション] 、 [デプロイ] の順に選択します。
- [自動検出] を選択します。
シークレットの確認
- AWS IoT コンソールにサインインし、 [テスト] を選択します。
- [トピックのサブスクリプション] に [secrets/output] と入力し、 [トピックへのサブスクライブ] を選択します。
- [トピックへサブスクライブする] を選択し、 [トピックのサブスクリプション] に [secrets/input] と入力し、 [トピックへのサブスクライブ] を選択します。
- [secrets/input] 、 [トピックに発行] の順に選択します。
- 画像では secret に なっていますが、 secrets が正しいです
- [secrets/output] を選択します。
- シークレットが表示されます。(数秒かかる場合があります)
シークレットのローテーション
シークレットを変更します。
- Secrets Manager コンソールにサインインします。
- [greengrass-TestSecret] を選択します。
- [シークレットの値を取得する] 、 編集するの順に選択します。
- シークレットの値を [123456] に変更します。
シークレットの確認の手順を実行します。 シークレットは変更前のままです。シークレットの更新を行った後は再度デプロイを行う必要があります。
Greengrass のデプロイの手順を実行します。 再度、シークレットの確認の手順を実行します。 シークレットが変更されている事を確認できました。
自動化したい場合は、Secrets MangaerのローテーションLambda関数を使用して、ローテーション後にデプロイを行うように実装すれば良さそうです。
あとがき
最近、業務でGreengrassを扱っているので、Greengrassのブログを書いてみました。 ローテーションに再デプロイが必要ですが、簡単・安全にシークレットを管理できて、とても便利ですね。